#include "playerpage.h"
#include "ui_playerpage.h"

#include "toast.h"
#include "util.h"
#include "vidhub.h"
#include <QShortcut>
#include <QJsonArray>

PlayerPage::PlayerPage(const model::VideoInfo& videoInfo, QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::PlayerPage)
    , videoInfo(videoInfo)
{
    ui->setupUi(this);

    // 设置无边框
    this->setWindowFlag(Qt::FramelessWindowHint);
    // 模态对话框
    //this->setAttribute(Qt::WA_ShowModal, true);

    // 初始化弹幕界面
    initBarrageArea();

    // 初始化视频界面信息
    updateVideoInfoUI();

    // 创建播放器
    mpv = new MpvPlayer(ui->screen, this);

    // 登录界面
    login = new Login();

    // 绑定快捷键
    QShortcut *shortCut = new QShortcut(ui->playBtn);
    QKeySequence keySequence(" ");
    shortCut->setKey(keySequence);
    connect(shortCut, &QShortcut::activated, this, [=](){
        ui->playBtn->animateClick();
    });

    // 最小化和关闭
    connect(ui->minBtn, &QPushButton::clicked, this, &QWidget::showMinimized);

    connect(ui->quitBtn, &QPushButton::clicked, this, &PlayerPage::onQuitBtnClicked);

    // 实例化⾳量调节窗⼝
    volume = new Volume(this);
    connect(ui->volumeBtn, &QPushButton::clicked, this, &PlayerPage::onVolumeBtnClicked);

    // 实例化倍速播放调节窗⼝
    playSpeed = new PlaySpeed(this);
    connect(ui->speedBtn, &QPushButton::clicked, this, &PlayerPage::onSpeedBtnClicked);

    // 点击我喜欢弹出登录界面
    connect(ui->likeImageBtn, &QPushButton::clicked, this, &PlayerPage::onLikeImageBtnClicked);

    // 暂停和播放
    connect(ui->playBtn, &QPushButton::clicked, this, &PlayerPage::onPlayBtnCkicked);

    // 用户头像点击
    connect(ui->userAvatar, &QPushButton::clicked, this, &PlayerPage::onUserAvatarBtnClicked);

    // 倍速调节
    connect(this->playSpeed, &PlaySpeed::setPlaySpeed, this, &PlayerPage::onPlaySpeedChanged);

    // 音量调节
    connect(this->volume, &Volume::setVolume, this, &PlayerPage::onVolumeChanged);

    // 当前播放时间
    connect(this->mpv, &MpvPlayer::playPositionChanged, this, &PlayerPage::onPlayPositionChanged);

    // 拖拽进度条控制播放时间
    connect(ui->videoSlider, &PlaySlider::setPlayProgress, this, &PlayerPage::onSetPlayProgress);

    // 开关弹幕
    connect(ui->bulletScreenBtn, &QPushButton::clicked, this, &PlayerPage::onBulletScreenBtnCkicked);

    // 发送弹幕
    connect(ui->bulletScreenText, &BarrageEdit::sendBulletScreen, this, &PlayerPage::onSendBulletScreenBtnClicked);

    // 所有视频分片播放结束信号槽绑定
    connect(mpv, &MpvPlayer::endOfPlaylist, this, &PlayerPage::onEndOfPlayList);


    // 检测是否点赞过
    likeCount = videoInfo.likeCount;
    auto dataCenter = model::DataCenter::getInstance();
    connect(dataCenter, &model::DataCenter::getIsLikeVdieoDone, this, [=](const QString& videoId, bool isLike){
        if(videoId != this->videoInfo.videoId){
            return;
        }

        if(isLike){
            ui->likeImageBtn->setStyleSheet("border-image : url(:/images/PlayPage/dianzan.png)");
        } else{
            ui->likeImageBtn->setStyleSheet("border-image : url(:/images/PlayPage/quxiaodianzan.png)");
        }

        this->isLike = isLike;
    });
    dataCenter->getIsLikeVdieoAsync(videoInfo.videoId);
}

PlayerPage::~PlayerPage()
{
    if(mpv) {
        delete mpv;
    }
    delete ui;
}

void PlayerPage::startPlaying()
{
    // 构造m3u8文件的url，然后交给mpv进行播放
    auto dataCenter = model::DataCenter::getInstance();
    QString m3u8FileUrl = dataCenter->getServerURL();
    m3u8FileUrl += "/HttpService/downloadVideo?fileId=";
    m3u8FileUrl += videoInfo.videoFileId;

    // 加载视频文件
    mpv->startPlay(m3u8FileUrl);

    // 加载弹幕
    loadBulletScreenData();

    // 点击播放时需要更新播放次数
    isUpdatePlayNum = false;

    // 初始化默认属性
    mpv->pause();
    mpv->setVolume(35);
    mpv->setPlaySpeed(1);
}

void PlayerPage::updateVideoInfoUI()
{
    // 设置视频标题
    ui->videoTittle->setText(videoInfo.videoTitle);
    // 设置视频播放时长
    QString curPlayTime = seconds2Time(0);
    QString totalTime = seconds2Time(videoInfo.videoDuration);
    ui->videoDuration->setText(curPlayTime + "/" + totalTime);
    // 设置用户昵称
    ui->userNikeName->setText(videoInfo.nickName);
    // 设置视频上传时间
    ui->loadupTime->setText(videoInfo.videoUpTime);
    // 设置点赞量
    ui->likeNum->setText(intToString(videoInfo.likeCount));
    // 设置播放量
    ui->playNum->setText(intToString(videoInfo.playCount));
    // 设置视频描述
    ui->videoDesc->setText(videoInfo.videoDesc);
}

void PlayerPage::updatePlayCount()
{
    // 如果视频的状态是待审核状态，则说明是管理员在审核视频，审核视频时不能点赞
    if(videoInfo.videoStatus == model::VideoStatus::waitForChecking){
        return;
    }

    // 更新界面上的播放数据
    videoInfo.playCount++;
    ui->playNum->setText(intToString(videoInfo.playCount));

    // 给服务器发送更新视频播放数的请求
    auto dataCenter = model::DataCenter::getInstance();
    dataCenter->setPlayNumberAsync(videoInfo.videoId);

    // 注意：更新dataCenter中视频列表中的播放次数：首页 和 我的页面
    // 首页视频列表中对应videoId的视频播放数
    auto videoListPtr = dataCenter->getVideoListPtr();
    videoListPtr->incrementPlayNum(videoInfo.videoId);
    // 我的视频列表
    auto userVideoListPtr = dataCenter->getVideoListPtr();
    if(!userVideoListPtr->videoInfos.isEmpty()){
        userVideoListPtr->incrementPlayNum(videoInfo.videoId);
    }

    // 状态视频列表
    auto statusVideoListPtr = dataCenter->getVideoListPtr();
    if(!statusVideoListPtr->videoInfos.isEmpty()){
        statusVideoListPtr->incrementPlayNum(videoInfo.videoId);
    }

    isUpdatePlayNum = true;

    emit increasePlayCount();
}



void PlayerPage::setUserIcon(QPixmap &userIcon)
{
    // 设置用户图像
    ui->userAvatar->setIcon(QIcon(userIcon));
}

void PlayerPage::mousePressEvent(QMouseEvent *event)
{
    QPoint point = event->position().toPoint();
    if(ui->playHead->geometry().contains(point))
    {
        if(event->button() == Qt::LeftButton)
        {
            dragPos = event->globalPosition().toPoint() - this->geometry().topLeft();
            return ;
        }
    }
    QWidget::mousePressEvent(event);
}

void PlayerPage::mouseMoveEvent(QMouseEvent *event)
{
    QPoint point = event->position().toPoint();
    if(ui->playHead->geometry().contains(point))
    {
        if(event->buttons() == Qt::LeftButton)
        {
            this->move(event->globalPosition().toPoint() - dragPos);

            QPoint point = this->geometry().topLeft();
            point.ry() += ui->playHead->height();
            barrageArea->move(point);

            return ;
        }
    }
    QWidget::mouseMoveEvent(event);
}

void PlayerPage::onQuitBtnClicked()
{
    if(likeCount != videoInfo.likeCount){
        // 视频的点赞信息发生改变, 同步到服务器
        auto dataCenter = model::DataCenter::getInstance();
        dataCenter->setLikeNumberAsync(videoInfo.videoId);

        // 清空弹幕数据
        dataCenter->setBarragesData(QJsonArray());

        // 更新视频列表中的videoId视频的点赞信息
        auto videoListPtr = dataCenter->getVideoListPtr();
        videoListPtr->updateLikeNumber(videoInfo.videoId, likeCount);
        videoInfo.likeCount = likeCount;

        // 更新我的页面中的视频列表 TODO
        auto userVideoListPtr = dataCenter->getVideoListPtr();
        if(!userVideoListPtr->videoInfos.isEmpty()){
            videoListPtr->updateLikeNumber(videoInfo.videoId, likeCount);
        }
        // 更新状态页面中的视频列表 TODO
        auto statusVideoListPtr = dataCenter->getVideoListPtr();
        if(!statusVideoListPtr->videoInfos.isEmpty()){
            videoListPtr->updateLikeNumber(videoInfo.videoId, likeCount);
        }

        // 通知首页中videoBox更新点赞数据
        emit updateLikeNum(likeCount);
    }
    this->deleteLater();
}

void PlayerPage::onVolumeBtnClicked()
{
    // 弹出音量调节窗口
    moveWindows(this->mapToGlobal(QPoint(0,0)));
    this->volume->show();
}

void PlayerPage::onSpeedBtnClicked()
{
    moveWindows(this->mapToGlobal(QPoint(0,0)));
    this->playSpeed->show();
}

void PlayerPage::moveWindows(const QPoint& point)
{
    QPoint newPoint = point + QPoint(this->width() - volume->width() - 13, 533);
    volume->move(newPoint);

    newPoint = point + QPoint(this->width() - playSpeed->width() - 80, 563);
    playSpeed->move(newPoint);
}

void PlayerPage::onLikeImageBtnClicked()
{
    auto dataCenter = model::DataCenter::getInstance();
    auto myselfInfo = dataCenter->getMyselfInfo();
    if(myselfInfo->isTempUser()){
        Toast::showMessage("先登录，登录完成之后才能点赞", login);
        return;
    }

    // 如果视频的状态是待审核状态，则说明是管理员在审核视频，审核视频时不能点赞
    if(videoInfo.videoStatus == model::VideoStatus::waitForChecking){
        Toast::showMessage("视频审核中禁止点赞!!!");
        return;
    }

    // 更新点赞按钮的图标
    isLike = !isLike;
    if(isLike){
        likeCount++;
        ui->likeImageBtn->setStyleSheet("border-image : url(:/images/PlayPage/dianzan.png)");
    }else{
        likeCount--;
        ui->likeImageBtn->setStyleSheet("border-image : url(:/images/PlayPage/quxiaodianzan.png)");
    }
    // 更新点赞数量
    ui->likeNum->setText(intToString(likeCount));
}

void PlayerPage::onPlayBtnCkicked()
{
    isPlay = !isPlay;
    if(isPlay) {
        ui->playBtn->setStyleSheet("#playBtn{ border-image : url(:/images/PlayPage/bofang.png)}");
        mpv->play();
    } else {
        ui->playBtn->setStyleSheet("#playBtn{ border-image : url(:/images/PlayPage/zanting.png)}");
        mpv->pause();
    }

    // 如果本次播放中，视频的播放数未更新时候再去更新
    if(!isUpdatePlayNum){
        updatePlayCount();
    }
}

void PlayerPage::onPlaySpeedChanged(double speed)
{
    mpv->setPlaySpeed(speed);
}

void PlayerPage::onVolumeChanged(int64_t volume)
{
    mpv->setVolume(volume);
}

void PlayerPage::onPlayPositionChanged(int64_t curPlayTime)
{
    // LOG() << "VidHub-playtime:" << this->curPlayTime << "-----mpv-palytime" << curPlayTime;
    QString  curTime = seconds2Time(curPlayTime);
    QString totalTime = seconds2Time(videoInfo.videoDuration);

    ui->videoDuration->setText(curTime + "/" + totalTime);

    ui->videoSlider->setPlayStep((double)curPlayTime / (double)videoInfo.videoDuration);

    if(isStartBS)
        showBulletScreen();
}

void PlayerPage::onSetPlayProgress(double playRatio)
{
    int64_t playTime = playRatio * videoInfo.videoDuration;
    mpv->setCurrentPlayPosition(playTime);
}

void PlayerPage::onBulletScreenBtnCkicked()
{
    isStartBS = !isStartBS;
    if(isStartBS) {
        ui->bulletScreenBtn->setStyleSheet("border-image:url(:/images/PlayPage/danmu.png)");
        barrageArea->show();
    } else {
        ui->bulletScreenBtn->setStyleSheet("border-image:url(:/images/PlayPage/danmuguan.png)");
        barrageArea->hide();
    }
}

void PlayerPage::onSendBulletScreenBtnClicked(const QString &text)
{
    // 如果视频的状态是待审核状态，则说明是管理员在审核视频，审核视频时不能点赞
    if(videoInfo.videoStatus == model::VideoStatus::waitForChecking){
        Toast::showMessage("视频审核中禁止发送弹幕!!!");
        return;
    }

    // 如果用户未登录，先要让用户登录，登录成功之后才能显示弹幕
    auto dataCenter = model::DataCenter::getInstance();
    auto myselfInfo = dataCenter->getMyselfInfo();
    if(myselfInfo->isTempUser()){
        Toast::showMessage("先登录，登录完成之后才能点赞", login);
        return;
    }

    // 如果弹幕是关闭的则⽆法发送弹幕
    if(!isStartBS){
        Toast::showMessage("请打开弹幕开关...");
        return;
    }

    // 构建弹幕信息
    BulletScreenItem* bs = new BulletScreenItem(top);
    QPixmap pixmap(":/images/homePage/touxiang.png");
    bs->setBulletScreenText(text);
    bs->setBulletScreenIcon(pixmap);
    int duration = 10 * 1000 + this->width() / (double)(30 + 18 + 1450);
    bs->setBulletScreenAnimal(this->width(), duration);
    bs->startAnimal();

    // 将弹幕数据发送到服务器
    model::BarrageInfo barrageInfo;
    barrageInfo.playTime = mpv->getPlayTime();
    barrageInfo.text = text;
    barrageInfo.userId = videoInfo.userId;

    dataCenter->loadupBarrageAsync(videoInfo.videoId, barrageInfo);
}

void PlayerPage::onEndOfPlayList()
{
    // 当整个视频播放结束之后，将播放按钮图标 以及 播放状态设置为暂停
    isPlay = false;
    ui->playBtn->setStyleSheet("border-image : url(:/images/PlayPage/zanting.png);");
    // 重新加载视频
    startPlaying();
}

void PlayerPage::onUserAvatarBtnClicked()
{
    // 关闭当前窗口
    onQuitBtnClicked();

    // 让BitPlayer切换页面
    VidHub::getInstance()->switchToUserInfoPage(videoInfo.userId);
}

QString PlayerPage::seconds2Time(int64_t seconds)
{
    QString time;
    // 拼接小时
    if(seconds / 60 / 60) {
        time += QString::asprintf("%02lld:", seconds/60/60);
    }
    // 拼接分和秒
    time += QString::asprintf("%02lld:%02lld", seconds/ 60, seconds % 60);
    return time;
}

void PlayerPage::initBarrageArea()
{
    // 创建弹幕的显示区域对话框, 该对话框没有边框 背景透明
    barrageArea = new QDialog(this);
    barrageArea->setMinimumSize(this->width(), 38 * 3);
    barrageArea->setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);
    barrageArea->setAttribute(Qt::WA_TranslucentBackground);

    // 创建布局管理器
    QVBoxLayout* layout = new QVBoxLayout(barrageArea);
    barrageArea->setLayout(layout);
    layout->setSpacing(0);
    layout->setContentsMargins(0,0,0,0);

    // 创建页面
    top = new QFrame(this);
    top->setFixedSize(this->width(), 38);

    middle = new QFrame(this);
    middle->setFixedSize(this->width(), 38);

    bottom = new QFrame(this);
    bottom->setFixedSize(this->width(), 38);

    layout->addWidget(top);
    layout->addWidget(middle);
    layout->addWidget(bottom);

    // 移动弹幕窗口到head下
    QPoint point = this->mapToGlobal(QPoint(0,0));
    point.setY(point.y() + ui->playHead->height());
    barrageArea->move(point);
    barrageArea->show();
}

void PlayerPage::loadBulletScreenData()
{
    // 加载弹幕数据
    auto dataCenter = model::DataCenter::getInstance();
    barrages = dataCenter->getBarragesData();
}

void PlayerPage::showBulletScreen()
{
    // 如果打开关闭时，则不需要添加弹幕到界面
    if(!isStartBS){
        return;
    }

    // 1. 获取当前playTime点的所有弹幕
    QList<model::BarrageInfo> bulletScrrenList = barrages.value(mpv->getPlayTime());
    BulletScreenItem* bsItem = nullptr;

    // 2. 将弹幕显示出来
    int xTop, xMiddle, xBottom;
    xTop = xMiddle = xBottom = top->width();
    for(int i = 0; i < bulletScrrenList.size(); ++i){
        model::BarrageInfo& bsInfo = bulletScrrenList[i];
        if(0 == i%3){
            // 弹幕显示在第一行
            bsItem = new BulletScreenItem(top);
            bsItem->setBulletScreenText(bsInfo.text);

            // 给弹幕设置动画属性
            int duration = 10000*xTop / (double)(top->width() + 30*18);
            bsItem->setBulletScreenAnimal(xTop, duration);
            xTop += bsItem->width() + 4*18; // 同一行间隔4个汉字，因为字体大小为18px，因此4*18，就是4个汉字的宽度

        }else if(1 == i%3){
            // 弹幕显示在第二行
            bsItem = new BulletScreenItem(middle);
            bsItem->setBulletScreenText(bsInfo.text);

            // 给弹幕设置动画属性
            int duration = 10000*xMiddle / (double)(middle->width() + 30*18);
            bsItem->setBulletScreenAnimal(xMiddle, duration);
            xMiddle += bsItem->width() + 4*18; // 同一行间隔4个汉字，因为字体大小为18px，因此4*18，就是4个汉字的宽度
        }else{
            // 弹幕显示在第三行
            bsItem = new BulletScreenItem(bottom);
            bsItem->setBulletScreenText(bsInfo.text);

            // 给弹幕设置动画属性
            int duration = 10000*xBottom / (double)(bottom->width() + 30*18);
            bsItem->setBulletScreenAnimal(xBottom + 2*18, duration);
            xBottom += bsItem->width() + 4*18; // 同一行间隔4个汉字，因为字体大小为18px，因此4*18，就是4个汉字的宽度
        }

        bsItem->startAnimal();
    }
}


